#pragma once 

#include "common.h"

#define _MAX_EVENT  9999 // 监听事件的数量
class CEpollServer
{
protected:
	struct Channel
	{
		int		 _fd;		  // socket 描述符
		int		 _event;	// 感兴趣事件
    std::string _buffer;	// 缓冲区

		Channel() : _fd(-1) ,_event(0){}
	};

  // socks5 服务器的三种状态
	enum Status
	{
		AUTH,			      // 身份认证
		ESTABLISHED,    // 确定连接
		FORWARD,		    // 转发
	};

	// 连接
	struct Connect
	{
		int     _counter;       // 计数器为 0 时，删除连接
		Status  _status;			  // socks5的状态，用于socks5 服务器
		Channel _clientChannel; // 客户端通道
		Channel _serverChannel; // 服务器通道

		Connect():_counter(0),_status(AUTH){}
	};

public:
	CEpollServer(int port)
		:_port(port)
		,_listenfd(-1)
		,_eventfd(-1)
	{}

	virtual ~CEpollServer()
	{
		if(_listenfd != -1)
			close(_listenfd);
	}

  // 设置成非阻塞
	void SetNonblocking(int sfd)
	{
		int flags = fcntl (sfd, F_GETFL, 0);
		if (flags == -1)
			ErrorLog("F_GETFL");

		flags |= O_NONBLOCK;
		int s = fcntl(sfd, F_SETFL, flags);
		if (s == -1)
			ErrorLog("F_SETFL");
	}

  // 操作 epoll 事件集
	void OperateEvent(int fd, int events, int how)
	{
		struct epoll_event event;
		event.events = events;
		event.data.fd = fd;
		if(-1 == epoll_ctl(_eventfd, how, fd, &event))
		{
			ErrorLog("epoll_ctl.fd:%d+how:%d", fd, how);
		}
	}
	
	// 启动服务，开始监听
	void StartUp();

	// 循环等待监听事件 
	void EventLoop();

	virtual void _DoConnectEventHandle(int fd) = 0;
	virtual void _DoReadEventHandle(int fd) = 0;
	virtual void _DoWriteEventHandle(int fd);

	void RemoveConnect(int fd);
	void SendInLoop(int fd, const char* buf, size_t len);
  void Forward(Channel* client_channel, Channel* server_channel, bool recv_decrypt, bool send_encrypt); 

// 防拷贝
private:
	CEpollServer(const CEpollServer&);
	CEpollServer& operator=(const CEpollServer&);

protected:
	int _listenfd; // 监听套接字
	int _port;	   // 服务端口
	int _eventfd;  // 事件描述
  std::map<int, Connect*> _connectMap; // 储存连接
}; // end of EpollServer

